import * as Cesium from '@cesium/Source/Cesium.js';

/**
 * GroundImage用来创建贴地图像，并且图像可以轮换
 * @memberof Obj
 * @class
 * @extends XbsjCzmObj
 */
var GroundImage = function(_XbsjCzmObj) {
  (0, _inherits3.default)(GroundImage, _XbsjCzmObj);

  function GroundImage(earth, guid) {
    (0, _classCallCheck3.default)(this, GroundImage);

    var _this = (0, _possibleConstructorReturn3.default)(this, (GroundImage.__proto__ || (0, _getPrototypeOf2.default)(GroundImage)).call(this, earth, guid));

    _this.disposers.push((0, _bind2.default)(_this, 'enabled', _this, 'show'));

    _this.textureWidth = 2048;
    _this.textureHeight = 2048;

    _XbsjBase2.default.registerPosition(_this);
    // 检测位置编辑状态 // positionEditing
    _this.disposers.push((0, _registerInteractionProperty.registerPositionEditing)(_this._earth, _this, {
      positionEditingProperty: 'editing'
    }));
    _this.disposers.push((0, _registerInteractionProperty.registerPositionPicking)(_this._earth, _this, {
      positionPickingProperty: 'creating'
    }));

    var scene = _this._earth.czm.scene;

    _this._groundPrimitive = undefined;
    _this.disposers.push(function() {
      _this._groundPrimitive && scene.groundPrimitives.remove(_this._groundPrimitive);
      _this._groundPrimitive = undefined;
    });

    _this._material = new Cesium.Material({
      fabric: {
        type: 'ImageMapXC',
        materials: {
          left: {
            type: 'ScaleImageXC',
            uniforms: {
              image: Cesium.Material.DefaultImageId,
              repeat: new Cesium.Cartesian2(1.0, 1.0),
              color: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
              stscale: new Cesium.Cartesian2(1.0, 1.0)
            },
            components: {
              diffuse: 'texture2D(image, fract(repeat * materialInput.st) * stscale).rgb * color.rgb',
              alpha: 'texture2D(image, fract(repeat * materialInput.st) * stscale).a * color.a'
            }
          },
          right: {
            type: 'ScaleImageXC',
            uniforms: {
              image: Cesium.Material.DefaultImageId,
              repeat: new Cesium.Cartesian2(1.0, 1.0),
              color: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
              stscale: new Cesium.Cartesian2(1.0, 1.0)
            },
            components: {
              diffuse: 'texture2D(image, fract(repeat * materialInput.st) * stscale).rgb * color.rgb',
              alpha: 'texture2D(image, fract(repeat * materialInput.st) * stscale).a * color.a'
            }
          }
        },
        uniforms: {
          t: 0.0,
          opacity: 1.0
        },
        components: {
          diffuse: 'left.diffuse * (1.0 - t) + right.diffuse * t',
          alpha: '(left.alpha * (1.0 - t) + right.alpha * t) * opacity'
        }
      }
    });

    var updateMaterialSize = function updateMaterialSize() {
      _this._leftHeatmapTexture && _this._leftHeatmapTexture.destroy();

      _this._leftHeatmapTexture = new Cesium.Texture({
        context: scene.context,
        width: _this.textureWidth,
        height: _this.textureHeight
      });

      _this._rightHeatmapTexture && _this._rightHeatmapTexture.destroy();

      _this._rightHeatmapTexture = new Cesium.Texture({
        context: scene.context,
        width: _this.textureWidth,
        height: _this.textureHeight
      });

      _this._material.materials.left.uniforms.image = _this._leftHeatmapTexture;
      _this._material.materials.right.uniforms.image = _this._rightHeatmapTexture;
      // this._material.materials.left.uniforms.color = new Cesium.Color(1, 0, 0, 1); test
    };

    updateMaterialSize();
    // this.disposers.push(reaction(() => ({
    //     width: this.textureWidth,
    //     height: this.textureHeight,
    // }), () => {
    //     updateMaterialSize();
    // }));

    _this._scratchRect = new Cesium.Rectangle();

    var updateGroundPrimitive = function updateGroundPrimitive() {
      _this._groundPrimitive && scene.groundPrimitives.remove(_this._groundPrimitive);
      _this._groundPrimitive = undefined;

      var ox = _this.origin[0];
      var oy = _this.origin[1];

      // const southWest = [...this.position].xePositionMove(-ox*this.width, -oy*this.height);
      // const eastNorth = [...this.position].xePositionMove((1.0-ox)*this.width, (1.0-oy)*this.height);
      // const rect = Cesium.Rectangle.fromRadians(southWest[0], southWest[1], eastNorth[0], eastNorth[1], this._scratchRect);

      // // 测试
      // var l = 1.9017002778972645 + 0.000018;
      // var b = 0.5972050595291177 + 0.000038;
      // var rect = Cesium.Rectangle.fromRadians(l - 0.000038, b - 0.000018, l + 0.000038, b + 0.000018);

      // this._groundPrimitive = scene.groundPrimitives.add(new Cesium.GroundPrimitive({
      //     geometryInstances: new Cesium.GeometryInstance({
      //         geometry: new Cesium.RectangleGeometry({
      //             rectangle: rect,
      //             vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
      //         })
      //     }),
      //     appearance: new Cesium.EllipsoidSurfaceAppearance({
      //         aboveGround: false
      //     }),
      //     // classificationType: Cesium.ClassificationType.TERRAIN
      //     // classificationType: Cesium.ClassificationType.CESIUM_3D_TILE
      //     classificationType: Cesium.ClassificationType.BOTH,
      // }));

      var groundImage = (0, _createGroundRectangle2.default)(_this.position, _this.width, _this.height, ox, oy, _this.rotation, undefined);
      _this._groundPrimitive = scene.groundPrimitives.add(groundImage);
      _this._groundPrimitive.show = _this.show; // 避免groundImage创建时设置show属性不起作用

      _this._groundPrimitive.appearance.material = _this._material;
    };

    updateGroundPrimitive();

    _this.disposers.push((0, _mobx.reaction)(function() {
      return {
        position: [].concat((0, _toConsumableArray3.default)(_this.position)),
        origin: [].concat((0, _toConsumableArray3.default)(_this.origin)),
        rotation: _this.rotation,
        width: _this.width,
        height: _this.height
      };
    }, function() {
      updateGroundPrimitive();
    }));

    _this.disposers.push((0, _mobx.reaction)(function() {
      return _this.show;
    }, function() {
      _this._groundPrimitive.show = _this.show;
    }));

    (0, _mobx.extendObservable)(_this, {
      _images: []
    });

    _this.disposers.push((0, _mobx.reaction)(function() {
      return [].concat((0, _toConsumableArray3.default)(_this.imageUrls));
    }, function(imageUrls) {
      _this._fetchTexturesSubscription && _this._fetchTexturesSubscription.unsubscribe();
      _this._fetchTexturesSubscription = undefined;

      var promises = imageUrls.map(function(e) {
        return new _promise2.default(function(resolve, reject) {
          Cesium.Resource.fetchImage({
            url: e
          }).then(function(image) {
            resolve(image);
          });
          // 这样写也可以
          // var img = new Image();
          // img.src = e;
          // img.onload = () => {
          //     resolve(img);
          // };
        });
      });

      var observable = new rxjs.Observable(function(observer) {
        _promise2.default.all(promises).then(function(images) {
          observer.next(images);
        });
      });

      _this._fetchTexturesSubscription = observable.subscribe(function(images) {
        var _this$_images;

        images = images.filter(function(e) {
          var r = e.width > _this.textureWidth || e.height > _this.textureHeight;
          if (r) {
            console.warn('\u8B66\u544A\uFF1A\u56FE\u7247\u5C3A\u5BF8\u5927\u4E8E' + _this
              .textureWidth + 'X' + _this.textureHeight +
              '\uFF0C\u5C06\u88AB\u5FFD\u7565\u3002\u3002');
          }
          return !r;
        });

        (_this$_images = _this._images).splice.apply(_this$_images, [0, _this._images.length]
          .concat((0, _toConsumableArray3.default)(images)));

        if (_this._images.length > 0) {
          var img = _this._images[0];
          if (_this.autoWidth) {
            _this.width = _this.height * img.naturalWidth / img.naturalHeight;
          } else if (_this.autoHeight) {
            _this.height = _this.width * img.naturalHeight / img.naturalWidth;
          }
        }
      });
    }));

    _this._leftImage = undefined;
    _this._rightImage = undefined;

    var whiteImageBuffer = new Uint8Array([255, 255, 255, 0]);

    var imageChanged = function imageChanged() {
      var l = _this._images.length;
      if (l === 0) {
        _this._leftImage = undefined;
        _this._rightImage = undefined;

        _this._material.materials.left.uniforms.image.copyFrom({
          width: 1,
          height: 1,
          arrayBufferView: whiteImageBuffer
        });
        _this._material.materials.left.uniforms.stscale = new Cesium.Cartesian2(1 / _this.textureWidth, 1 /
          _this.textureHeight);

        _this._material.materials.right.uniforms.image.copyFrom({
          width: 1,
          height: 1,
          arrayBufferView: whiteImageBuffer
        });
        _this._material.materials.right.uniforms.stscale = new Cesium.Cartesian2(1 / _this.textureWidth, 1 /
          _this.textureHeight);

        return;
      }

      var currentTime = _this.currentTime > _this.timeDuration ? 0.0 : _this.currentTime;

      var index = 0;
      var intervalT = 0;

      // 等间距的操作模式
      if (l >= 2) {
        if (!_this.times || _this.times.length === 0) {
          var interval = _this.timeDuration / (l - 1);
          var pos = currentTime / interval;
          index = Math.floor(pos);
          intervalT = pos - index;
        } else {
          index = _this.times.findIndex(function(time) {
            return time > currentTime;
          }) - 1;
          if (index < 0) {
            index = 0;
            intervalT = 0;
          } else if (index >= _this._images.length - 1) {
            index = _this._images.length - 2;
            intervalT = 1.0;
          } else {
            intervalT = (currentTime - _this.times[index]) / (_this.times[index + 1] - _this.times[index]);
          }
        }
      }

      if (_this._leftImage !== _this._images[index]) {
        _this._leftImage = _this._images[index];
        var image = _this._leftImage;
        _this._material.materials.left.uniforms.image.copyFrom(image);
        _this._material.materials.left.uniforms.stscale = new Cesium.Cartesian2(image.width / _this
          .textureWidth, image.height / _this.textureHeight);
      }

      if (l >= 2 && _this._rightImage !== _this._images[index + 1]) {
        _this._rightImage = _this._images[index + 1];
        var _image = _this._rightImage;
        _this._material.materials.right.uniforms.image.copyFrom(_image);
        _this._material.materials.right.uniforms.stscale = new Cesium.Cartesian2(_image.width / _this
          .textureWidth, _image.height / _this.textureHeight);
      }

      _this._material.uniforms.t = intervalT;
    };

    imageChanged();
    _this.disposers.push((0, _mobx.reaction)(function() {
      return {
        currentTime: _this.currentTime,
        timeDuration: _this.timeDuration,
        images: [].concat((0, _toConsumableArray3.default)(_this._images)),
        times: [].concat((0, _toConsumableArray3.default)(_this.times))
      };
    }, imageChanged));

    (0, _mobx.extendObservable)(_this, {
      _pathPlayingListener: undefined,
      get playing() {
        return !!this._pathPlayingListener;
      },
      set playing(val) {
        if (!!val && !this._pathPlayingListener) {
          this._play();
        } else if (!val && this._pathPlayingListener) {
          this._pathPlayingListener = this._pathPlayingListener && this._pathPlayingListener();
        }
      }
    }, {
      _pathPlayingListener: _mobx.observable.ref,
      playing: _mobx.computed
    });

    _this.disposers.push(function() {
      _this.playing = false;
    });

    var updateOpacity = function updateOpacity() {
      _this._material.uniforms.opacity = _this.opacity;
    };
    updateOpacity();
    _this.disposers.push((0, _mobx.reaction)(function() {
      return _this.opacity;
    }, updateOpacity));
    return _this;
  }

  (0, _createClass3.default)(GroundImage, [{
    key: '_play',
    value: function _play() {
      var _this2 = this;

      var scene = this._earth.czm.scene;

      // 如果位于末端，则从头开始
      if (this.currentTime === this.timeDuration) {
        this.currentTime = 0;
      }

      var lastTimeStamp = Date.now();
      this._pathPlayingListener = scene.postUpdate.addEventListener(function(scene, time) {
        var currentTimestamp = Date.now();
        var diffTimeStamp = currentTimestamp - lastTimeStamp;
        lastTimeStamp = currentTimestamp;
        var currentTime = _this2.currentTime + diffTimeStamp * 0.001;
        if (_this2.loopPlay) {
          if (currentTime > _this2.timeDuration) {
            _this2.currentTime = 0;
          } else {
            _this2.currentTime = currentTime;
          }
        } else {
          if (currentTime > _this2.timeDuration) {
            _this2.currentTime = _this2.timeDuration;
            _this2._pathPlayingListener = _this2._pathPlayingListener && _this2
              ._pathPlayingListener();
          } else {
            _this2.currentTime = currentTime;
          }
        }
      });
    }
  }, {
    key: 'flyTo',
    value: function flyTo() {
      this._earth.camera.flyTo(this.position, this.width, [0, -Math.PI / 3, 0]);
    }
  }, {
    key: 'destroy',
    value: function destroy() {
      return (0, _get3.default)(GroundImage.prototype.__proto__ || (0, _getPrototypeOf2.default)(
        GroundImage.prototype), 'destroy', this).call(this);
    }
  }]);
  return GroundImage;
}(_XbsjCzmObj3.default);


GroundImage.defaultOptions = {
  position: [0, 0, 0],
  width: 100,
  height: 100,
  autoWidth: false,
  autoHeight: true,
  origin: [0.5, 0.5],
  rotation: 0.0,
  // textureWidth: 1024,
  // textureHeight: 1024,
  show: true,
  // ground: true,
  imageUrls: [],
  timeDuration: 1.0, // 单位秒
  currentTime: 0.0,
  loopPlay: true,
  times: [],
  opacity: 1.0
};

var xbsjSchema = {
  title: "GroundImage Property",
  type: "object",
  properties: {
    /**
     * 显示
     * @type {boolean}
     * @instance
     * @default true
     * @memberof Obj.GroundImage
     */
    show: {
      type: "boolean",
      title: "显示",
      default: true,
      description: '显示'
    },
    /**
     * @description 原点
     * @type {array}
     * @instance
     * @default [0.5, 0.5]
     * @memberof Obj.GroundImage
     */
    origin: {
      type: "array",
      items: {
        type: 'number'
      },
      minItems: 2,
      maxItems: 2,
      title: "原点",
      default: [0.5, 0.5],
      description: '原点'
    },
    /**
     * @description 旋转角
     * @type {number}
     * @instance
     * @default 0
     * @memberof Obj.GroundImage
     */
    rotation: {
      type: "number",
      title: "旋转角",
      default: 0,
      description: '旋转角'
    },
    /**
     * @description 位置数组 [经度、纬度、高度]
     * @type {array}
     * @instance
     * @default [0, 0, 0]
     * @memberof Obj.GroundImage
     */
    position: {
      type: "array",
      items: {
        type: 'number'
      },
      minItems: 3,
      maxItems: 3,
      title: "位置数组",
      default: [0, 0, 0],
      description: '位置数组'
    },
    /**
     * 宽度
     * @type {number}
     * @instance
     * @default 100
     * @memberof Obj.GroundImage
     */
    width: {
      type: "number",
      title: "东西方向长度",
      default: 100,
      description: '宽度'
    },
    /**
     * 高度
     * @type {number}
     * @instance
     * @default 100
     * @memberof Obj.GroundImage
     */
    height: {
      type: "number",
      title: "南北方向长度",
      default: 100,
      description: '高度'
    },
    /**
     * 是否自动计算宽度，根据高度和载入的图像自动计算宽度
     * @type {boolean}
     * @instance
     * @default true
     * @memberof Obj.GroundImage
     */
    autoWidth: {
      type: "boolean",
      title: "是否自动计算宽度",
      default: true,
      description: '是否自动计算宽度'
    },
    /**
     * 是否自动计算高度，根据宽度和载入的图像自动计算高度
     * @type {number}
     * @instance
     * @default true
     * @memberof Obj.GroundImage
     */
    autoHeight: {
      type: "boolean",
      title: "是否自动计算高度",
      default: true,
      description: '是否自动计算高度'
    },
    /**
     * 图像路径数组，形式如 ['xxx/xxx.jpg', 'zzz/zzz.png']
     * @type {string[]}
     * @instance
     * @default ''
     * @memberof Obj.GroundImage
     */
    imageUrls: {
      type: "array",
      items: {
        type: 'string'
      },
      title: "图像路径",
      default: [],
      description: '图像路径'
    },
    /**
     * 播放总时长，单位秒
     * @type {number}
     * @instance
     * @default 1.0
     * @memberof Obj.GroundImage
     */
    timeDuration: {
      type: "number",
      title: "播放总时长",
      default: 1.0,
      description: '播放总时长'
    },
    /**
     * 当前播放时刻，单位秒
     * @type {number}
     * @instance
     * @default 0.0
     * @memberof Obj.GroundImage
     */
    currentTime: {
      type: "number",
      title: "当前播放时刻",
      default: 0.0,
      description: '当前播放时刻'
    },
    /**
     * 是否循环播放
     * @type {boolean}
     * @instance
     * @default true
     * @memberof Obj.GroundImage
     */
    loopPlay: {
      type: "boolean",
      title: "是否循环播放",
      default: true,
      description: '是否循环播放'
    },
    /**
     * 每个图象的播放时刻<br/>
     * 警告：当length为0时，会使用timeDuration来均衡播放；length>0时，timeDuration属性将失效！
     * @type {number[]}
     * @instance
     * @default []
     * @memberof Obj.GroundImage
     * @example
     * x.imageUrls = ['xxx.jpg', 'ccc.png', 'ddd.png']; //
     * // 注意确保时刻总是升序，即数字由小到大，最后一个数字同时也表示了整个轮播的总时长
     * x.times = [0, 5, 6]; // 相当于第一张图片在0s出现，第二张图片在5s出现，0s-5s之间会从第一张图片过渡到第二张图片
     */
    times: {
      type: "boolean",
      title: "每个图象的播放时刻",
      default: [],
      description: '每个图象的播放时刻'
    },
    /**
     * 不透明度
     * @type {number}
     * @instance
     * @default 1.0
     * @memberof Obj.GroundImage
     */
    opacity: {
      type: "number",
      title: "不透明度",
      default: 1.0,
      description: "不透明度"
    }
  }
};

GroundImage.xbsjSchema = xbsjSchema;
